package societyGames.document.model
{
import flash.events.EventDispatcher;
import flash.filesystem.File;
import flash.filesystem.FileMode;
import flash.filesystem.FileStream;

/**
 * A document that supports undo.
 */
public class Document extends EventDispatcher
{
  private var _commandStack:CommandStack = new CommandStack();
  protected var _file:File;

  [Bindable]
  public var isDirty:Boolean = false;

  [Bindable]
  public function get commandStack():CommandStack
  {
    return this._commandStack;
  }

  public function set commandStack(value:CommandStack):void
  {
    //Just to suppress warning.
  }

  //Load from the specified file.
  public function load(file:File):void
  {
    var fileStream:FileStream = new FileStream();
    fileStream.open(file, FileMode.READ);
    try
    {
      loadFromFileStream(fileStream);
      this._commandStack.clear();
      this._file = file;
    }
    finally
    {
      fileStream.close();
    }
  }

  protected function loadFromFileStream(fileStream:FileStream):void
  {
    //Override this.
  }

  //Save to the specified file. If file is null saves to existing file if there is one.
  public function save(file:File = null):void
  {
    if (file == null && this._file == null)
    {
      throw new ArgumentError("Cannot save to existing file if there is no existing file.");
    }
    if (file == null)
    {
      file = this._file;
    }
    var fileStream:FileStream = new FileStream();
    fileStream.open(file, FileMode.WRITE);
    try
    {
      saveToFileStream(fileStream);
      this._file = file;
      commandStack.saved();
      isDirty = false;
    }
    finally
    {
      fileStream.close();
    }
  }

  protected function saveToFileStream(fileStream:FileStream):void
  {
    //Override this.
  }

  public function get hasFile():Boolean
  {
    return this._file != null;
  }

  /**
   *
   * @param fragmentClass
   * @param args String Representing document paths for this fragment.
   * @return
   */
  public function createFragment(fragmentClass:Class):Fragment
  {
    var fragment:Fragment = new fragmentClass();
    fragment.initialize(this);
    return fragment;
  }
}
}